package com.gsc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gsc.constants.SystemConstants;
import com.gsc.domain.ResponseResult;
import com.gsc.domain.dto.MenuListDto;
import com.gsc.domain.entity.Menu;
import com.gsc.domain.entity.RoleMenu;
import com.gsc.domain.vo.MenuVo;
import com.gsc.mapper.MenuMapper;
import com.gsc.mapper.RoleMenuMapper;
import com.gsc.utils.BeanCopyUtils;
import com.gsc.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gsc.service.MenuService;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author makejava
 * @since 2023-02-16 13:42:11
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public List<String> selectPermsByUserId(Long id) {
        //根据用户id查询权限关键字 ，如果是超级管理员，返回所有的权限
            //注：用户id为1的管理员为超级管理员，拥有所有权限
        if(SecurityUtils.isAdmin()){
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            //查询菜单类型为"C"或"F"的
            queryWrapper.in(Menu::getMenuType,SystemConstants.MENU_TYPE,SystemConstants.BUTTON_TYPE);
            queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(queryWrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回当前用户所具有的的权限
            //获取 MenuMapper, 自定义方法进行连表查询（查询用户拥有的角色，根据角色查询所拥有的菜单，再获得菜单对应的关键字）
        return getBaseMapper().selectPermsByUserId(id);
    }

    @Override
    public List<MenuVo> selectRouterMenuTreeByUserId(Long userId) {
        //获取mapper
        MenuMapper menuMapper = getBaseMapper();
        List<MenuVo> menuVos = null;
        List<Menu> menus = null;
        //判断是否是管理员
        if(SecurityUtils.isAdmin()){
            //如果是返回所有符合要求的menu
            menus = menuMapper.selectAllRouterMenu();
            menuVos = BeanCopyUtils.copyBeanList(menus, MenuVo.class);
        }else {
            //否则返回当前用户所拥有的menu
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
            menuVos = BeanCopyUtils.copyBeanList(menus, MenuVo.class);
        }
        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单，设置到children属性中
        List<MenuVo> menuTree = builderMenuTree(menuVos, 0L);
        return menuTree;
    }


    @Override
    public List<Menu> selectMenuList(MenuListDto menuListDto) {
        //模糊查询 按照父菜单id和orderNum进行排序
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(menuListDto.getMenuName()),Menu::getMenuName,menuListDto.getMenuName());
        queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_MENU);
        queryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum);
        //查询菜单列表
        MenuMapper baseMapper1 = getBaseMapper();
        List<Menu> menus = baseMapper1.selectList(queryWrapper);
        //返回数据
        return menus;
    }

    @Override
    public Menu selectMenu(Long id) {
        //根据id查询菜单信息
        Menu menu = menuMapper.selectById(id);
        //返回菜单信息
        return menu;
    }

    @Override
    public void updateMenu(Menu menu) {
        //修改菜单
        menuMapper.updateById(menu);
    }

    @Override
    public boolean hasChild(Long menuId) {
        //判断menuId是不是其他菜单的父id
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId,menuId);
        return count(queryWrapper)!=0;
    }

    @Override
    public List<Menu> treeSelectMenu(Menu menu) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        //menuName模糊查询
        queryWrapper.like(StringUtils.hasText(menu.getMenuName()),Menu::getMenuName,menu.getMenuName());
        queryWrapper.eq(StringUtils.hasText(menu.getStatus()),Menu::getStatus,menu.getStatus());
        //排序 parent_id和order_num
        queryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum);
        List<Menu> menus = list(queryWrapper);;
        return menus;
    }

    @Override
    public List<Long> selectMenuListByRoleId(Long id) {
        MenuMapper menuMapper = getBaseMapper();
        return menuMapper.selectMenuListByRoleId(id);
    }


    /**
     * 构建树的方法
     * menuVo.setChildren(getChildren(menuVo,menuVos))；获取菜单的子菜单集合，并且赋值给菜单
     * @param menuVos
     * @param
     * @return
     */
    private List<MenuVo> builderMenuTree(List<MenuVo> menuVos, Long parentId) {
        List<MenuVo> menuVoTree = menuVos.stream()
                .filter(menuVo -> menuVo.getParentId().equals(parentId))
                .map(menuVo -> menuVo.setChildren(getChildren(menuVo, menuVos)))
                .collect(Collectors.toList());
        return menuVoTree;
    }

    /**
     * 获取传入参数的子菜单集合
     * map(menuVo1 -> menuVo1.setChildren(getChildren(menuVo1,menuVos))) ：递归，自己调用自己，找出子菜单的子菜单
     * @param menuVo
     * @param menuVos
     * @return
     */
    private List<MenuVo> getChildren(MenuVo menuVo, List<MenuVo> menuVos) {
        //只保留父id是menuVo的id的菜单
        List<MenuVo> menuVoList = menuVos.stream()
                .filter(menuVo1 -> menuVo1.getParentId().equals(menuVo.getId()))
                .map(menuVo1 -> menuVo1.setChildren(getChildren(menuVo1,menuVos)))
                .collect(Collectors.toList());

        return menuVoList;
    }
}
